/**
 * 
 */
package jvs.tea.html;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import x.java.io.File;
import x.java.io.File.Index;

/**
 * @author qiangli
 * 
 */
public class FolderTemplateInputStream extends FileObjectInputStream {
	private static final String[] TYPES = new String[] { "application/",
			"text/", "image/", "audio/", "video/" };

	private static final String[][] NEW_ACTIONS = new String[][] {
			{ "newfolder", "newfolder.png", "New folder" },
			{ "link", "link.png", "Link resource" },
			{ "edit", "editor.png", "Edit text" },
			{ "record", "microphone.png", "Record sound" },
			{ "camera", "camera.png", "Take pictures" },
			{ "camcorder", "videocamera.png", "Shoot video" } };

	private static final String[][] DEFAULT_MENU = new String[][] {
		{ "v-bin-shell:///bin/about", "", "About" } };
	
	private static final String[][] ROOT_MENU = new String[][] {
			{ "v-bin-shell:///bin/about", "", "About" } };

	private static final String[][] FOLDER_MENU = new String[][] {
			{ "v-bin-shell:///bin/newmenu", "", "New..." }, 
			{ "v-bin-shell:///bin/about", "", "About" } };

	private static final String[][] EMPTYFOLDER_MENU = new String[][] {
			{ "v-bin-shell:///bin/delete", "", "Delete" }, 
			{ "v-bin-shell:///bin/rename", "", "Rename" },
			{ "v-bin-shell:///bin/about", "", "About" } };

	private static final String FOLDER_TPL = Constant.TEMPLATE_DIR
			+ "folder.htm";

	private static final int FOLDER_TPL_MAX_SIZE = 4096;

	private static final SimpleDateFormat df = new SimpleDateFormat(
			"yyyy-MM-dd HH:mm");

	private static final ByteArrayInputStream folderIS;

	private static final String BIN_HTM = "bin/htm";

	//private static final String BIN_ICON = "bin/icon";

	static {
		try {
			InputStream is = FolderTemplateInputStream.class
					.getResourceAsStream(FOLDER_TPL);
			byte[] b = new byte[FOLDER_TPL_MAX_SIZE];
			int read = -1;
			int len = b.length;
			for (int i = 0; i < len; i += read) {
				read = is.read(b, i, len - i);
				if (read == -1) {
					len = i;
					break;
				}
			}
			folderIS = new ByteArrayInputStream(b, 0, len);
		} catch (IOException e) {
			e.printStackTrace();
			// no way we can continue
			throw new RuntimeException(e);
		}
	}

	synchronized private static InputStream getFolderIS() {
		folderIS.reset();
		return folderIS;
	}

	private List<Index> indice;
	
	private File.Info[] files;
	
	private int total;
	
	private int fileindex;
	
	private int pagesize = 10;

	public FolderTemplateInputStream(URI context, URI asset, File.Info file, int fileindex,
			int pagesize, int total, List<Index> indice, File.Info[] files) {
		super(context, asset, file);
		this.fileindex = fileindex;
		this.pagesize = pagesize;
		this.total = total;
		this.indice = indice;
		this.files = files;
		init();
	}

	private void init() {
		final long starttime = System.currentTimeMillis();
		final String path = file.getPath();
		addInjector("breadcrumb", makeBreadcrumbs(root, path, file.isDirectory()));

		final StringBuilder sb = new StringBuilder();
		//
		for(Index i: indice) {
			int idx = i.pos;
			String n = i.name;
			if (idx == fileindex) {
				sb.append("<span class=\"fileindex-selected\">");
			} else {
				sb.append("<span class=\"fileindex\">");
			}
			sb.append("<a href=\"");
			encodeCommand(sb, BIN_HTM, path + "?fileindex=" + idx
					+ "&type=text/html");
			sb.append("\">");
			sb.append(n);
			sb.append("</a></span>");
		}
		addInjector("fileindex", sb.toString());
		//
		final boolean isRoot = file.isRoot();
		final boolean isEmpty = (total == 0);
		final boolean canWrite = file.canWrite;
		// page content
		if (isEmpty == false) {
			sb.setLength(0);
			if (files != null) {
				Date date = new Date();
				for (int i = 0; i < files.length; i++) {
					date.setTime(files[i].lastModified);
					format(sb, path, files[i].getName(), files[i]
							.getDisplayName(), files[i].isFile(), files[i]
							.length, date, files[i].getContentType());
				}
				addInjector("filecontent", sb.toString());
			}
			// index range begin - end of total
			int begin = fileindex + 1;
			int end = Math.min((fileindex + pagesize), total);
			sb.setLength(0);
			sb.append(begin);
			sb.append(" - ");
			sb.append(end);
			sb.append(" of ");
			sb.append(total);
			addInjector("filetotal", sb.toString());
			//
			// smart new actions - only show if no. of entries is less then page size
			if (((end - fileindex) < pagesize) && canWrite == true && (isRoot == false)) {
				sb.setLength(0);
				sb.append("<hr class=\"dotline\" />");
				smartaction(sb, NEW_ACTIONS, path);
				addInjector("actionbar", sb.toString());
			}
		} else {
			//empty folder
			sb.setLength(0);
			emptycontent(sb, path , canWrite);
			addInjector("filecontent", sb.toString());
		}
		// menu
		sb.setLength(0);
		if (isRoot == true) {
			menu(sb, ROOT_MENU, path);
		} else {
			if (canWrite) {
				if (isEmpty == true) {
					menu(sb, EMPTYFOLDER_MENU, path);
				} else {
					menu(sb, FOLDER_MENU, path);
				}
			} else {
				menu(sb, DEFAULT_MENU, path);
			}
		}
		addInjector("menu", sb.toString());
		//
		final long now = System.currentTimeMillis();
		addInjector("elapsed", "" + (now - starttime));
		setInputStream(getFolderIS());
	}

	private void emptycontent(StringBuilder sb, String path, boolean canWrite) {
		sb.append("<tr><td></td></tr>");
		sb.append("<tr><td>Folder is empty</td></tr>");
		sb.append("<tr><td></td></tr>");
		if (canWrite == true) {
			for (int i = 0; i < NEW_ACTIONS.length; i++) {
				String[] ai = NEW_ACTIONS[i];
				String cmd = "v-bin-shell:///bin/" + ai[0] + "!" + path;
				sb.append("<tr>");
				sb.append("<td><img src=\"" + iconpath);
				sb.append(ai[1]);
				sb.append("\" />");
				sb.append("&nbsp;<a  class=\"file-link\" href=\"");
				sb.append(cmd);
				sb.append("\" target=\"_self\" >");
				sb.append(ai[2]);
				sb.append("</a></td>");
				sb.append("</tr>");
			}
		}
	}

	private String icon(String contentType) {
		if (contentType.startsWith("text/html")) {
			return "text_html.png";
		}
		if (contentType.startsWith("text/tea")) {
			return "text_tea.png";
		}
		int type = 0;

		for (int i = 0; i < TYPES.length; i++) {
			if (contentType.startsWith(TYPES[i])) {
				type = i;
				break;
			}
		}
		switch (type) {
		case x.java.io.File.TYPE_TEXT:
			return "text.png";
		case x.java.io.File.TYPE_AUDIO:
			return "audio.png";
		case x.java.io.File.TYPE_IMAGE:
			return null; // "image.png";
		case x.java.io.File.TYPE_VIDEO:
			return "video.png";
		}
		return "application.png";
	}

	private void format(StringBuilder sb, String path, String name,
			String display, boolean isFile, long length, Date date, String type) {
		//final String hl = "onmouseover=\"this.style.backgroundColor='lightblue';\""
		//		+ " onmouseout=\"this.style.backgroundColor='white';\"";
		StringBuilder pa = new StringBuilder();
		pa.append("this,'");
		pa.append(path);
		pa.append("',");
		pa.append("'");
		pa.append(name);
		pa.append("',");
		pa.append("'");
		pa.append(isFile);
		pa.append("',");
		pa.append("'");
		pa.append(type);
		pa.append("'");
		//
		final String hl = "onmouseover=\"onOver("+pa+");\""
				+ " onmouseout=\"onOut("+pa+");\"";
		sb.append("<tr ");
		sb.append(hl);
		sb.append(">");
		String pathname = pathcat(path, name);
		if (name.endsWith(".zip")) {
			sb.append("<td><img src=\"" + iconpath);
			sb.append("filefolder.png");
		} else if (name.endsWith(File.LINK_EXT)) {
			sb.append("<td><img src=\"" + iconpath);
			sb.append("link.png");
		} else if (isFile) {
			// sb.append("application.png");
			String icon = icon(type);
			if (icon == null) {
				// a known image type
				sb.append("<td><img src=\"");
				sb.append("content://v:/bin/icon!" + pathname);
				//encodeCommand(sb, BIN_ICON, pathname);
			} else {
				sb.append("<td><img src=\"" + iconpath);
				sb.append(icon);
			}
		} else {
			// folder
			sb.append("<td><img src=\"" + iconpath);
			sb.append("folder.png");
		}
		sb.append("\" />");
		sb.append("</td><td><a  class=\"file-link\" href=\"");

		if (isFile) {
			// htm
			if (name.endsWith(".htm") || name.endsWith(".html")) {
				sb.append(pathname); //
			} else {
				encodeCommand(sb, BIN_HTM, pathname + "?type=text/html");
			}
		} else {
			// folder
			sb.append(pathname);
			sb.append("/");
		}
		sb.append("\" target=\"");
		sb.append(isFile ? "_blank" : "_self");
		sb.append("\" title=\"");
		sb.append(name);
		if (!isFile) {
			sb.append("/");
		}
		sb.append("\">");
		sb.append(shorten(display, MAX_NAME_LEN));
		if (!isFile) {
			sb.append("/");
		}
		sb.append("</a></td><td align=\"right\"><span class=\"file-size\">");
		if (isFile) {
			File.formatSize(length, sb);
		}
		sb.append("</span></td><td><span class=\"file-date\">");
		sb.append(df.format(date));
		sb.append("</span></td></tr>");
	}

	private static String pathcat(String path, String name) {
		boolean end = path.endsWith("/");
		boolean start = name.startsWith("/");
		if (!end && !start) {
			return path + "/" + name;
		}
		if (end && start) {
			return path + name.substring(1);
		}
		return path + name;
	}

	private void encodeCommand(StringBuilder sb, String cmd, String args) {
		try {
			sb.append(context);
			sb.append(cmd);
			sb.append("!");
			sb.append(args.replace('?', '!'));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
